#ifndef MIPS_H
#define MIPS_H

#include "string.h"
#include "misc.h"
#include <stdlib.h>
void fetch();
void issue();
void reg();
void execute();
void memB();
void write_back();
void commit();
void compare();
// input ports -- holds the input values driven on the previous cycle
struct {

	int reset;
	int inst_i_valid;
	u64 inst_i_line;
	
	u64 mem_i_line;
	int mem_i_dest_m;
	int mem_i_ctrl_m;
	int mem_i_line_valid_m;

} ports_i;

// output ports
struct {
	int inst_o_valid;
	int inst_o_addr;

	int mem_o_data;
	int mem_o_addr;
	int mem_o_dest_reg;
	int mem_o_ctrl;
	int mem_o_line_valid;

} ports_o, ports_o_test;

typedef struct {
	int rs;
	int rd;
	int rt;
	int opcode;
	int funct;
	int imm_extended;
}inst;

// global instruction buffers

int fetch_inst_A;
int issue_inst_A;
int reg_inst_A;
int ex_inst_A;
int wb_inst_A;

int fetch_inst_B;
int issue_inst_B;
int reg_inst_B;
int ex_inst_B;
int mem_inst_B;
int wb_inst_B;

// regfile
int regfile[32];

//branch decision variable from ex stage
int branch_decA;
int branch_decB;
int branch_countA;
int branch_countB;

//memory data
struct node {
   int reg_dest;
   int ctrl;
   int valid;
   struct node* next;
};

struct node* headn ;
void Pop(struct node** , int *, int *, int  *);
void AppendNode(struct node** , int , int , int);

//hazard 
int mem_o_hazard;
int valid_mem;
int memory_inst;

//issue global vars
int scoreboard[32]; // scoreboard
int temp_occupied_bit[16]; // dont worry about temp variables
int temp_rstag[16];
int temp_rttag[16];
int temp_branchtag[16];

int branch_decision; // this is the branch decision, 1-taken, 2-not taken
int br_count; // this is the fedback branch count after the ex stage
int rd1_broadcast,rd0_broadcast,rd1_broadcast_v,rd0_broadcast_v; //these are the rd values broadcast from the write_backstage
int inst1, inst0;// the two instructions from the fetch stage that go into issue
int inst_valid1, inst_valid0;// the valids corresponding to the above instructions
int rs1_valid,rs0_valid,rt1_valid,rt0_valid,rd1_valid,rd0_valid; // valids from rs,rt,rd 
int branch_dep1,branch_dep0,mem_tag1,mem_tag0; // branch_tags, memtags
int branch_count1, branch_count0, mem_count1, mem_count0; //branch_counts, mem_counts
int full; //full signal

//queue related variables
int rs[16],rt[16];
int inst_[16];
int inst_valid[16];
int branch_tag[16];
int mem_tag[16];
int branch_count[16];
int mem_count[16];
int rs_tag[16];
int rt_tag[16];
int occupied_bit[16];

int mem_counter; //this is the mem_counter for the issue stage. Use a diffferent counter for the fetch
int mem_valid[16];//dont worry about this

int pe_A[16];
int found_qaddrA,qaddrA;
int instA_issue; // output inst to pipe A from issue
int branch_countA_issue;// output branch_countA to pipeA from issue

int pe_B[16];
int found_qaddrB,qaddrB;
int instB_issue; // output inst to pipe B from issue
int branch_countB_issue;// output branch_countB to pipeB from issue

int found_wr_addr1,found_wr_addr0,wr_addr1,wr_addr0; // dont worry about these

int rs1_tag_temp,rs0_tag_temp,rt1_tag_temp,rt0_tag_temp; // nor about these

#endif
